#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>

using namespace std;

class Edge {
public:
    int src, dest, weight;

    Edge(int src, int dest, int weight) : src(src), dest(dest), weight(weight) {}
};

class CompareEdges {
public:
    bool operator()(const Edge& e1, const Edge& e2) {
        return e1.weight > e2.weight; // Compare edges based on their weights in ascending order
    }
};

class Graph {
private:
    int numVertices;
    vector<Edge> edges;

public:
    Graph(int numVertices) : numVertices(numVertices) {}

    void addEdge(int src, int dest, int weight) {
        edges.push_back(Edge(src, dest, weight));
    }

    int findRoot(vector<int>& parent, int v) {
        if (parent[v] == v)
            return v;
        return findRoot(parent, parent[v]);
    }

    void unionSets(vector<int>& parent, int v1, int v2) {
        int root1 = findRoot(parent, v1);
        int root2 = findRoot(parent, v2);
        parent[root2] = root1;
    }
//    void removeEdge(std::vector<int>& parent, int v1, int v2) {
//        int root1 = findRoot(parent, v1);
//        int root2 = findRoot(parent, v2);
//        // 如果两个顶点的根节点不相等，说明它们之间存在连接，将其断开
//        if (root1 != root2) {
//            parent[v2] = v2;  // 将v2的根节点设置为自身，表示独立成为一个集合
//        }
//    }


    void kruskalMST() {
        vector<Edge> result;
        sort(edges.begin(), edges.end(), [](const Edge& e1, const Edge& e2) {
            return e1.weight < e2.weight;
        });

        vector<int> parent(numVertices);
        for (int v = 0; v < numVertices; ++v) {
            parent[v] = v;
        }

        priority_queue<Edge, vector<Edge>, CompareEdges> pq;
        for (const auto& edge : edges) {
            pq.push(edge);
        }
        int sum=0;
        while (!pq.empty()) {
            Edge edge = pq.top();
            pq.pop();
            int root1 = findRoot(parent, edge.src);
            int root2 = findRoot(parent, edge.dest);
            if (root1 != root2) {
                result.push_back(edge);
                sum+=edge.weight;
                unionSets(parent, root1, root2);
            }
            if(result.size()==numVertices-1){
                parent[root2]=root2;
                break;
            }
        }
        if(result.size()<numVertices-1){
            cout<<"No MST"<<endl;
            cout<<numVertices-result.size();
            return;
        }

        Edge edge_1 = result.back();
        result.pop_back();
        int sum2=sum;
        sum2 -= edge_1.weight;
        while (!pq.empty()) {
            Edge edge = pq.top();
            pq.pop();
            int root1 = findRoot(parent, edge.src);
            int root2 = findRoot(parent, edge.dest);
            if (root1 != root2) {
                result.push_back(edge);
                sum2+=edge.weight;
                unionSets(parent, root1, root2);
            }
            if(result.size()==numVertices-1){
                break;
            }
        }
        if(sum==sum2){
            cout<<sum<<endl;
            cout<<"No";
        }
        if(sum!=sum2){
            cout<<sum<<endl;
            cout<<"Yes";
        }
//        cout << "Minimum Spanning Tree:" << endl;
//        for (const auto& edge : result) {
//            cout << edge.src << " - " << edge.dest << " weight: " << edge.weight << endl;
//        }
    }
};
int main() {

    int m,n;
    cin>>m>>n;
    int u;
    Graph graph(m);
    for(int i=0;i<n;i++){
        int a,b,c;
        cin>>a>>b>>c;
        u=c;
        graph.addEdge(a-1,b-1,c);
    }
    if(m==1){
        cout<<0<<endl;
        cout<<"Yes"<<endl;
        return 0;
    }
    graph.kruskalMST();
}